<?php

namespace EthanZ\LaravelExt\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use EthanZ\LaravelExt\Exceptions\NormalException;
use Illuminate\Support\Str;

/**
 * 验证器基类
 */
class BaseRequest extends FormRequest
{

    protected string $currentScene;


    public function __construct()
    {
        // 获取当前场景.
        $action             = request()?->route()?->getActionName();
        $currentScene       = explode('@', $action)[1];
        $this->currentScene = $currentScene;

        parent::__construct();
    }


    /**
     *  是否开启验证
     *
     * @return boolean 结果
     */
    public function authorize(): bool
    {
        return true;
    }


    /**
     *  错误返回
     *
     * @param Validator $validator 所有场景.
     *
     * @return void
     * @throws NormalException 验证|返回.
     */
    protected function failedValidation(Validator $validator): void
    {
        $error = $validator->errors()->all();
        $msg   = '';
        foreach ($error as $k => $v) {
            if ($k === 0) {
                $msg .= $v;
            } else {
                $msg .= '；' . $v;
            }
        }

        throw new NormalException('BAS_PAM_002', msg: $msg);
    }


    /**
     *  添加字段规则
     *
     * @param array $addFieldRule 所需添加的字段规则.
     * @param array $rules        所有规则场景.
     */
    protected function addFieldRule(array $addFieldRule, array &$rules): void
    {
        // 如果存在添加验证字段.
        if (isset($addFieldRule[$this->currentScene]) && $addFieldRule[$this->currentScene]) {
            // 循环添加验证规则.
            foreach ($addFieldRule[$this->currentScene] as $k => $v) {
                // 存在则追加，不存在则新增.
                if (isset($rules[$k])) {
                    $rules[$k] .= '|' . $v;
                } else {
                    $rules[$k] = $v;
                }
            }
        }
    }


    /**
     *  删除字段规则
     *
     * @param array $delFieldRule 所需删除的字段规则.
     * @param array $rules        所有规则场景.
     */
    protected function delFieldRule(array $delFieldRule, array &$rules): void
    {
        // 如果存在删除验证字段.
        if (isset($delFieldRule[$this->currentScene]) && $delFieldRule[$this->currentScene]) {
            // 循环删除验证规则.
            foreach ($delFieldRule[$this->currentScene] as $k => $v) {
                // 存在则删除.
                if (isset($rules[$k])) {
                    $fieldRule = explode('|', $rules[$k]);
                    $delRule   = explode('|', $v);
                    $rulesArr  = array_diff($fieldRule, $delRule);
                    $rules[$k] = implode('|', $rulesArr);
                }
            }
        }
    }


    /**
     *  重置规则
     *
     * @param array $resFieldRule 所需重置的字段.
     * @param array $rules        所有规则场景.
     */
    protected function resFieldRule(array $resFieldRule, array &$rules): void
    {
        // 如果存在重置验证字段.
        if (isset($resFieldRule[$this->currentScene]) && $resFieldRule[$this->currentScene]) {
            // 循环重置验证规则.
            foreach ($resFieldRule[$this->currentScene] as $k => $v) {
                $rules[$k] = $v;
            }
        }
    }


    /**
     *  获取规则
     *
     * @param array $scenes 所有场景.
     * @param array $rules  所有规则场景.
     *
     * @return array 结果
     * @throws NormalException
     */
    protected function getRule(array $scenes, array $rules): array
    {
        // 取得场景验证.
        $needValidator = $scenes[$this->currentScene] ?? [];
        if (!$needValidator) {
            return [];
        }
        // 循环获取验证规则.
        $rule = [];
        foreach ($rules as $k => $v) {
            $key = substr($k, 0, strpos($k, '.'));
            // 获取需要验证的规则.
            if (in_array($k, $needValidator, true) || in_array($key, $needValidator, true)) {
                // 存在unique且需要忽略id.
                if (Str::contains($v, ['{', '}'])) {
                    // 获取字段.
                    $field = Str::between($v, '{', '}');
                    // 获取传入值
                    $fieldValue = request($field);
                    if (!$fieldValue) {
                        throw new NormalException('BAS_PAM_003', msg: Str::replaceFirst(':attribute', $field, trans('validation.required')));
                    }

                    // 改为laravel内部验证.
                    $v = Str::replaceFirst('{' . $field . '}', $fieldValue, $v);
                }

                $rule[$k] = $v;
            }
        }

        return $rule;
    }
}
